<template>
  <div class="voice-chat-container">
    <h2>语音聊天室</h2>
    <div class="controls">
      <button @click="startRecording" :disabled="isRecording">开始录音</button>
      <button @click="stopRecording" :disabled="!isRecording">停止录音</button>
      <button @click="playRecording" :disabled="!audioBlob">播放录音</button>
      <button @click="sendRecording" :disabled="!audioBlob">发送录音</button>
      <button @click="saveRecording" :disabled="!audioBlob">保存录音</button>

      <!-- 隐藏的文件输入框，用于加载录音 -->
      <input
          type="file"
          id="audioFileInput"
          accept=".wav,audio/*"
          @change="loadRecording"
          style="display: none"
      >
      <button @click="triggerFileInput">加载录音</button>
    </div>
    <!-- 波形显示区域 -->
    <div ref="waveform" class="waveform"></div>
    <!-- 接收到的音频消息区域 -->
<!--    <div class="received-audios">-->
<!--      <h3>收到的语音消息</h3>-->
<!--      &lt;!&ndash; 遍历所有收到的音频消息 &ndash;&gt;-->
<!--      <div v-for="(audio, index) in receivedAudios" :key="index" class="audio-message">-->
<!--        &lt;!&ndash; 消息标题（序号和名称） &ndash;&gt;-->
<!--        <p>消息 {{ index + 1 }} - {{ audio.name || '未命名' }}</p>-->
<!--        <div class="audio-controls">-->
<!--          &lt;!&ndash; HTML5音频播放器 &ndash;&gt;-->
<!--          <audio controls :src="audio.url"></audio>-->
<!--          &lt;!&ndash; 音频操作按钮组 &ndash;&gt;-->
<!--          <div class="audio-buttons">-->
<!--            &lt;!&ndash; 删除按钮 &ndash;&gt;-->
<!--            <button @click="deleteAudio(index)">删除</button>-->
<!--            &lt;!&ndash; 保存按钮 &ndash;&gt;-->
<!--            <button @click="saveReceivedAudio(index)">保存</button>-->
<!--            &lt;!&ndash; 播放按钮 &ndash;&gt;-->
<!--            <button @click="playReceivedAudio(index)">播放</button>-->
<!--          </div>-->
<!--        </div>-->
<!--      </div>-->
<!--    </div>-->
  </div>
</template>

<script setup>
// 导入Vue相关功能
import { ref, onMounted, onBeforeUnmount } from 'vue';
// 导入录音库
import RecordRTC from 'recordrtc';
// 导入波形显示库
import WaveSurfer from 'wavesurfer.js';
// 导入WebSocket客户端
import io from 'socket.io-client';

// 状态管理
const isRecording = ref(false); // 是否正在录音
const audioBlob = ref(null); // 当前录音的Blob对象
const receivedAudios = ref([]); // 接收到的音频消息数组
const waveform = ref(null); // 波形显示容器的引用
const wavesurfer = ref(null); // WaveSurfer实例
const recorder = ref(null); // RecordRTC录音器实例
const socket = ref(null); // Socket.IO连接实例
const audioElements = ref({}); // 音频元素引用（未使用）

// 组件挂载时执行的初始化逻辑
onMounted(() => {
  // 初始化WaveSurfer波形显示
  wavesurfer.value = WaveSurfer.create({
    // container: waveform.value, // 绑定到DOM元素
    waveColor: '#4a4a88', // 波形颜色
    progressColor: '#2c3e50', // 进度条颜色
    cursorColor: '#2c3e50', // 光标颜色
    barWidth: 2, // 波形条宽度
    barRadius: 3, // 波形条圆角
    cursorWidth: 1, // 光标宽度
    height: 100, // 波形高度
    barGap: 2, // 波形条间距
    responsive: true // 响应式
  });

  // 初始化Socket.IO连接
  socket.value = io('http://localhost:3000');

  // 监听音频消息事件
  socket.value.on('audio-message', (audioData) => {
    // 将接收到的ArrayBuffer转换为Blob
    const audioBlob = new Blob([new Uint8Array(audioData.data)], { type: 'audio/wav' });
    // 创建对象URL用于播放
    const audioUrl = URL.createObjectURL(audioBlob);
    // 添加到接收到的音频列表
    receivedAudios.value.push({
      url: audioUrl,
      blob: audioBlob,
      name: audioData.name || `语音消息_${new Date().toLocaleString()}` // 默认名称
    });
    // 保存到本地存储
    saveToLocalStorage();
  });

  // 尝试从本地存储加载录音
  loadFromLocalStorage();
});

// 组件卸载前的清理工作
onBeforeUnmount(() => {
  // 销毁WaveSurfer实例
  if (wavesurfer.value) {
    wavesurfer.value.destroy();
  }
  // 断开Socket.IO连接
  if (socket.value) {
    socket.value.disconnect();
  }
  // 清理所有音频对象的URL，防止内存泄漏
  receivedAudios.value.forEach(audio => {
    URL.revokeObjectURL(audio.url);
  });
});

// 开始录音
const startRecording = async () => {
  try {
    // 请求麦克风权限并获取音频流
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    // 初始化录音器
    recorder.value = new RecordRTC(stream, {
      type: 'audio', // 录音类型
      mimeType: 'audio/wav', // 音频格式
      recorderType: RecordRTC.StereoAudioRecorder, // 录音器类型
      desiredSampRate: 16000, // 采样率
      numberOfAudioChannels: 1, // 声道数
      timeSlice: 1000, // 切片时间（用于实时传输）
      ondataavailable: (blob) => {
        // 实时传输时可以在这里发送数据块
      }
    });

    // 开始录音
    recorder.value.startRecording();
    // 更新录音状态
    isRecording.value = true;
  } catch (error) {
    // 处理麦克风访问错误
    console.error('无法访问麦克风:', error);
    alert('无法访问麦克风，请检查权限设置');
  }
};

// 停止录音
const stopRecording = () => {
  if (recorder.value) {
    // 停止录音
    recorder.value.stopRecording(() => {
      // 获取录音Blob
      audioBlob.value = recorder.value.getBlob();
      // 加载到WaveSurfer
      wavesurfer.value.load(URL.createObjectURL(audioBlob.value));
      // 更新录音状态
      isRecording.value = false;
    });
  }
};

// 播放当前录音
const playRecording = () => {
  if (audioBlob.value) {
    // 播放WaveSurfer中的音频
    wavesurfer.value.play();
  }
};

// 播放接收到的特定音频
const playReceivedAudio = (index) => {
  // 获取对应的audio元素
  const audioElement = document.querySelectorAll('.received-audios audio')[index];
  if (audioElement) {
    // 播放音频
    audioElement.play();
  }
};

// 发送录音
const sendRecording = () => {
  if (!audioBlob.value || !socket.value) return;

  // 使用FileReader读取Blob
  const reader = new FileReader();
  reader.onload = () => {
    // 获取ArrayBuffer
    const arrayBuffer = reader.result;
    // 提示用户输入消息名称
    const name = prompt('请输入语音消息名称', `语音消息_${new Date().toLocaleString()}`);
    // 通过Socket.IO发送音频数据
    socket.value.emit('audio-message', {
      data: Array.from(new Uint8Array(arrayBuffer)), // 转换为普通数组
      name: name || undefined // 使用用户输入的名称或undefined
    });
  };
  // 读取Blob为ArrayBuffer
  reader.readAsArrayBuffer(audioBlob.value);
};

// 删除接收到的音频
const deleteAudio = (index) => {
  // 释放对象URL
  URL.revokeObjectURL(receivedAudios.value[index].url);
  // 从数组中移除
  receivedAudios.value.splice(index, 1);
  // 更新本地存储
  saveToLocalStorage();
};

// 保存当前录音到本地文件
const saveRecording = () => {
  if (!audioBlob.value) return;

  // 提示用户输入文件名
  // const name = prompt('请输入保存的文件名', `录音_${new Date().toLocaleString()}.wav`);
  const name = `录音_${new Date().toLocaleString()}.wav`;
  if (!name) return;

  // 创建对象URL
  const url = URL.createObjectURL(audioBlob.value);
  // 创建下载链接
  const a = document.createElement('a');
  a.href = url;
  // 设置下载文件名
  a.download = name.endsWith('.wav') ? name : `${name}.wav`;
  // 触发下载
  document.body.appendChild(a);
  a.click();
  // 清理
  setTimeout(() => {
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }, 100);
};

// 触发文件选择对话框
const triggerFileInput = () => {
  const fileInput = document.getElementById('audioFileInput');
  fileInput.value = ''; // 清除之前的选择
  fileInput.click(); // 触发点击
};

// 从文件加载录音
const loadRecording = (event) => {
  const file = event.target.files[0];
  if (!file) return;

  // 验证文件类型
  if (!file.type.startsWith('audio/') && !file.name.endsWith('.wav')) {
    alert('请选择有效的音频文件');
    return;
  }

  // 使用FileReader读取文件
  const reader = new FileReader();
  reader.onload = (e) => {
    // 获取ArrayBuffer
    const arrayBuffer = e.target.result;
    // 创建Blob
    const blob = new Blob([arrayBuffer], { type: file.type || 'audio/wav' });
    // 保存到状态
    audioBlob.value = blob;
    // 加载到WaveSurfer
    wavesurfer.value.load(URL.createObjectURL(blob));

    // 自动播放
    setTimeout(() => {
      wavesurfer.value.play();
    }, 500);
  };
  // 读取文件为ArrayBuffer
  reader.readAsArrayBuffer(file);
};

// 保存接收到的音频到本地文件
const saveReceivedAudio = (index) => {
  const audio = receivedAudios.value[index];
  // 提示用户输入文件名
  const name = prompt('请输入保存的文件名', `${audio.name || '语音消息'}.wav`);
  if (!name) return;

  // 创建下载链接
  const a = document.createElement('a');
  a.href = audio.url;
  // 设置下载文件名
  a.download = name.endsWith('.wav') ? name : `${name}.wav`;
  // 触发下载
  document.body.appendChild(a);
  a.click();
  // 清理
  setTimeout(() => {
    document.body.removeChild(a);
  }, 100);
};

// 保存接收到的音频到本地存储
const saveToLocalStorage = () => {
  // 准备要保存的数据
  const audiosToSave = receivedAudios.value.map(audio => ({
    name: audio.name,
    data: Array.from(new Uint8Array(audio.blob)) // 转换为普通数组
  }));
  // 保存到localStorage
  localStorage.setItem('savedAudios', JSON.stringify(audiosToSave));
};

// 从本地存储加载音频
const loadFromLocalStorage = () => {
  // 从localStorage获取数据
  const savedAudios = localStorage.getItem('savedAudios');
  if (savedAudios) {
    try {
      // 解析JSON
      const parsedAudios = JSON.parse(savedAudios);
      // 遍历并恢复音频
      parsedAudios.forEach(audio => {
        // 将数组转换回Blob
        const audioBlob = new Blob([new Uint8Array(audio.data)], { type: 'audio/wav' });
        // 创建对象URL
        const audioUrl = URL.createObjectURL(audioBlob);
        // 添加到接收列表
        receivedAudios.value.push({
          url: audioUrl,
          blob: audioBlob,
          name: audio.name
        });
      });
    } catch (e) {
      // 处理错误
      console.error('加载本地存储的音频失败:', e);
      localStorage.removeItem('savedAudios');
    }
  }
};
</script>

<style scoped>
.voice-chat-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  font-family: 'Arial', sans-serif;
}

.controls {
  margin: 20px 0;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

button {
  padding: 8px 16px;
  background-color: #4a4a88;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button:hover:not(:disabled) {
  background-color: #3a3a78;
}

button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}

input[type="file"] {
  display: none;
}

.waveform {
  margin: 20px 0;
  background: #f5f5f5;
  border-radius: 4px;
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}

.received-audios {
  margin-top: 30px;
  border-top: 1px solid #eee;
  padding-top: 20px;
}

.audio-message {
  margin: 15px 0;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 6px;
  background: #f9f9f9;
}

.audio-controls {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.audio-buttons {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.audio-buttons button {
  padding: 6px 12px;
  font-size: 0.85em;
}

audio {
  width: 100%;
  max-width: 400px;
  outline: none;
}

h2, h3 {
  color: #4a4a88;
}

h3 {
  margin-bottom: 15px;
  font-size: 1.2em;
}
</style>